#pragma once
#include<iostream>
#include<queue>
#include<pthread.h>
using namespace std;

template<class T>
class thread_pool
{
  private:

  std::queue<T> q;
  pthread_mutex_t lock;
  pthread_cond_t cond;
  thread_pool()
  //  :pthread_mutex_init(&lock,nullptr)
  {
    pthread_mutex_init(&lock,nullptr);
    pthread_cond_init(&cond,nullptr);
  }
  thread_pool(thread_pool<T>& )=delete;
  thread_pool<T>& operator=(thread_pool<T>&)=delete;
  static thread_pool<T>* instance;
  public:

  static thread_pool<T>* get_instance()
  {
    static pthread_mutex_t mtx;
    pthread_mutex_init(&mtx,nullptr);
     if(instance==nullptr)
     {
      pthread_mutex_lock(&mtx);
      if(instance==nullptr)
      {
        instance=new thread_pool<T>();
      }
      pthread_mutex_unlock(&mtx);
     }
     return instance;
  }

  bool is_empty()
  {
    return q.size()==0;
  }
  void Lock()
  {
    pthread_mutex_lock(&lock);
  }
  void Unlock()
  {
    pthread_mutex_unlock(&lock);
  }
  void thread_wakeup()
  {
    pthread_cond_signal(&cond);
  }

  void push_task(const T& task)
  {
    Lock();
    q.push(task);
    thread_wakeup();
    Unlock();
  }
  void get_task(T& task)
  {
    task=q.front();
    q.pop();
  }

  static void* Routine(void* args)//因为Routine函数默认只能有一个参数，所以不能作为普通成员函数(隐含this指针)
  {
    pthread_detach(pthread_self());//线程分离
    thread_pool<T>* tp=(thread_pool<T>*)args;
     while(true)
     {
       tp->Lock();
       while(tp->is_empty())//为空就等待
       {
         pthread_cond_wait(&(tp->cond),&(tp->lock));
       }
       T task;
       tp->get_task(task);
      tp->Unlock();
      task();
   }
  }
  void thread_pool_init(size_t t)
  {
    for(int i=0;i<t;i++)
    {
      pthread_t tid;
      pthread_create(&tid,nullptr,Routine,this);
    }
  }

      ~thread_pool()
        {
            pthread_mutex_destroy(&lock);
            pthread_cond_destroy(&cond);
        }
};
template<class T>
thread_pool<T>*  thread_pool<T>::instance=nullptr;
